package org.yaukie.auth.config;

import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.CorsFilter;
import org.yaukie.auth.filter.JwtAuthenticationFilter;
import org.yaukie.auth.handler.LoginOutSuccessHandler;
import org.yaukie.auth.handler.UnAuthorizationHandler;
import org.yaukie.base.text.Convert;
import org.yaukie.base.util.StringTools;

@ConditionalOnProperty(
        prefix = "yaukie.auth",
        name = {"enabled"},
        havingValue = "true"
)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
        prePostEnabled = true
)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private static final Logger log = LoggerFactory.getLogger(WebSecurityConfig.class);
    @Value("${yaukie.auth.enabled}")
    private String enabled;
    @Value("${yaukie.auth.encoder.type:default}")
    private String ifMd5;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;
    @Autowired
    private LoginOutSuccessHandler loginOutSuccessHandler;
    @Autowired
    private UnAuthorizationHandler unAuthorizationHandler;
    @Autowired
    private CorsFilter corsFilter;

    public WebSecurityConfig() {
    }

    @PostConstruct
    public void init() {
        if (log.isInfoEnabled()) {
            if (Convert.toBool(this.enabled)) {
                log.info("已开启登录认证模块...系统将提供认证机制...");
            } else {
                log.info("未开启登录认证模块...");
            }
        }

    }

    protected void configure(HttpSecurity http) throws Exception {
        ((HttpSecurity)((HttpSecurity)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((ExpressionUrlAuthorizationConfigurer.AuthorizedUrl)((HttpSecurity)((HttpSecurity)http.csrf().disable()).sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()).authorizeRequests().antMatchers(HttpMethod.GET, new String[]{"/config/**", "/css/**", "/fonts/**", "/img/**", "/js/**", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js"})).permitAll().antMatchers(new String[]{"/sso/login", "/capcha/verifyImg"})).anonymous().antMatchers(new String[]{"/provider/**"})).anonymous().antMatchers(new String[]{"/api/xjob/getJobImage"})).anonymous().antMatchers(new String[]{"/api/xtrans/getTransImage"})).anonymous().antMatchers(new String[]{"/op/xlog/downLog/**"})).anonymous().antMatchers(new String[]{"/help/**"})).anonymous().antMatchers(new String[]{"/profile/**"})).anonymous().antMatchers(new String[]{"/swagger-*.html"})).anonymous().antMatchers(new String[]{"/swagger-resources/**"})).anonymous().antMatchers(new String[]{"/webjars/**"})).anonymous().antMatchers(new String[]{"/*/api-docs"})).anonymous().antMatchers(new String[]{"/druid/**"})).anonymous().anyRequest()).authenticated().and()).exceptionHandling().authenticationEntryPoint(this.unAuthorizationHandler).and()).headers().frameOptions().disable();
        http.logout().logoutUrl("/logout").logoutSuccessHandler(this.loginOutSuccessHandler);
        http.addFilterBefore(this.jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        http.addFilterBefore(this.corsFilter, JwtAuthenticationFilter.class);
        http.addFilterBefore(this.corsFilter, LogoutFilter.class);
    }

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        if (StringTools.equals("md5", this.ifMd5)) {
            Md5PasswordEncoder md5PasswordEncoder = (Md5PasswordEncoder)this.passwordMd5Encoder();
            md5PasswordEncoder.setSalt("yuenbinisagreatman!");
            auth.userDetailsService(this.userDetailsService).passwordEncoder(md5PasswordEncoder);
            log.info("系统使用MD5加密方式......");
        } else {
            auth.userDetailsService(this.userDetailsService).passwordEncoder(this.passwordEncoder());
            log.info("系统使用强散列加密方式......");
        }

    }

    @Bean
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @ConditionalOnProperty(
            prefix = "yaukie.auth.encoder",
            value = {"type"},
            havingValue = "md5"
    )
    @Bean
    public PasswordEncoder passwordMd5Encoder() {
        return Md5PasswordEncoder.getInstance();
    }
}
